package com.boot2.core.dao.batch.insert;

import com.boot2.core.lifecycle.SmartLifecycleHandler;
import com.boot2.core.utils.ThreadPoolTaskExecutorUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;

/**
 * @author zhangweilin
 * @Description: 批量提交
 * @date 2019/7/7
 */
@Component
@EnableAsync(proxyTargetClass = true)
public class BatchCommitHandler implements SmartLifecycleHandler {

    /**
     * 待提交任务数量的线程池
     */
    private static final ThreadPoolTaskExecutor executor = ThreadPoolTaskExecutorUtil.createThreadPoolTaskExecutor(0.5);

    protected Log loger = LogFactory.getLog(this.getClass());

    @Autowired(required = false)
    List<BatchCommitWare<?>> batchCommitWareList;

    @Autowired(required = false)
    List<BatchCommitInit> batchCommitInitList;

    static Map<String, BatchCommitData> batchCommitDataMap;

    @Autowired(required = false)
    public void BatchCommitDataMap(Map<String, BatchCommitData> batchCommitDataMap) {
        BatchCommitHandler.batchCommitDataMap = batchCommitDataMap;
    }

    /**
     * 获取批量提交的载体对象
     *
     * @param key
     * @param <T>
     * @return
     */
    public static synchronized <T> BatchCommit<T> getBatchCommit(String key) {
        BatchCommit<T> batchCommit = initBatchCommit(key);
        return batchCommit;
    }


    /**
     * 获取批量提交的载体对象
     *
     * @param key
     * @param batchCommitSize    每次批量最多提交的数量
     * @param intervalCommitTime 每次批量提交的间隔时间,单位毫秒
     * @param <T>
     * @return
     */
    public static synchronized <T> BatchCommit<T> getBatchCommit(String key, int batchMaxCommitSize, long intervalCommitTime) {
        BatchCommit<T> batchCommit = initBatchCommit(key);
        batchCommit.setBatchMaxCommitSize(batchMaxCommitSize);
        batchCommit.setIntervalCommitTime(intervalCommitTime);
        BatchCommitInvoker.taskMapQueue.put(key, batchCommit);
        return batchCommit;
    }

//
//    /**
//     * 获取批量提交的载体对象
//     *
//     * @param key
//     * @param batchCommitSize    每次批量最多提交的数量
//     * @param intervalCommitTime 每次批量提交的间隔时间,单位毫秒
//     * @param batchCommitSize 此值表示队列中积累到这个数量就立刻提交，与定时无关
//     * @param <T>
//     * @return
//     */
//    public static synchronized <T> BatchCommit<T> getBatchCommit(String key, int batchMaxCommitSize, long intervalCommitTime,int batchCommitSize) {
//        BatchCommit<T> batchCommit = initBatchCommit(key);
//        batchCommit.setBatchMaxCommitSize(batchMaxCommitSize);
//        batchCommit.setIntervalCommitTime(intervalCommitTime);
//        batchCommit.setBatchCommitSize(batchCommitSize);
//        return batchCommit;
//    }

    /**
     * 通过key初始化
     *
     * @param key
     * @param <T>
     * @return
     */
    private static <T> BatchCommit<T> initBatchCommit(String key) {
        Map<String, BatchCommit<?>> taskMapQueue = BatchCommitInvoker.taskMapQueue;
        BatchCommit<T> batchCommit = (BatchCommit<T>) taskMapQueue.get(key);
        if (null == batchCommit) {
            batchCommit = new BatchCommit<>(key);
            batchCommit.setBatchCommitDataMap(batchCommitDataMap);
            taskMapQueue.put(key, batchCommit);
            batchCommit.getBatchCommitData().init(key);
        }
        return batchCommit;
    }


    @Override
    @Async
    public void hand() {
        if (null == batchCommitWareList) {
            return;
        }
        if (null != batchCommitInitList) {
            batchCommitInitList.forEach(e -> {
                e.init();
            });
        }
        if (CollectionUtils.isNotEmpty(batchCommitWareList)) {
            batchCommitWareList.forEach(e -> {
////                //定时刷入库
//                BatchCommitInvoker scheduleBatchCommitInvoker = e.getScheduleBatchCommitInvoker();
//                executor.submit(() -> {
//                    try {
//                        scheduleBatchCommitInvoker.invoke();
//                    } catch (InterruptedException e1) {
//                        e1.printStackTrace();
//                        loger.error("定时批量入库失败,e:" + e, e1);
//                    }
//                });

//                //队满或定时刷入库
                BatchCommitInvoker queueFullOrScheduleBatchCommitInvoker = e.getQueueFullOrScheduleBatchCommitInvoker();
                executor.setBeanName("batchCommitExecutor_");
                executor.submit(() -> {
                    try {
                        queueFullOrScheduleBatchCommitInvoker.invoke();
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                        loger.error("队满批量入库失败,e:" + e, e1);
                    }
                });
            });
        }
    }
}
